package main

import (
	"bytes"
	"fmt"
	"github.com/go-redis/redis"
	"log"
	"src/model/ProtoModel"
	"src/test/demo"
	"src/utils"
	"strconv"
	"time"
)

var client *redis.Client

func init() {
	client = redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "123456", // 如果没有设置密码，则为空字符串
		DB:       0,        // 使用默认数据库
	})
}

/**
channelName 通道名
num 间隔多少次打印
*/
// Golang：通过Redis消息订阅
func subs1(channelName string, num int) {
	now := time.Now()
	// fmt.Println(now.Unix()) // 1565084298 秒fmt.Println(now.UnixNano()) // 1565084298178502600 纳秒fmt.Println(now.UnixNano() / 1e6) // 1565084298178 毫秒
	fmt.Println("end【0 】——————————开始接收订阅消息—————————!")
	fmt.Println(now.UnixNano() / 1e6)
	fmt.Println(now.Unix())
	/// 订阅channel1这个channel
	sub := client.Subscribe(channelName)
	//// 取消订阅
	//submodel.Unsubscribe("channel1")
	// submodel.Channel() 返回go channel，可以循环读取redis服务器发过来的消息
	var b = 1
	for m := range sub.Channel() {
		if b%num == 0 {
			//fmt.Println("run【", b, "】——————————接收订阅消息中—————————!")
			fmt.Println("耗时秒", (time.Now()).Unix()-now.Unix(), "耗时毫秒", ((time.Now()).UnixNano()/1e6)-(now.UnixNano()/1e6))
			fmt.Printf("run【"+strconv.Itoa(b)+"】订阅： channel=%s message=%s\n", m.Channel, m.Payload)
			//fmt.Println("run【", b, "】订阅：", m.Payload)
		}
		b++
		// 打印收到的消息
		//fmt.Println(msg.Channel)
		//fmt.Println(msg.Payload)
	}
	//fmt.Println("耗时秒", (time.Now()).Unix()-now.Unix())
	//fmt.Println("耗时毫秒", ((time.Now()).UnixNano()/1e6)-(now.UnixNano()/1e6))
	//fmt.Println("end【", b, "】——————————接收订阅完毕—————————!")
}

func sub4(channel string) {
	defer func() {
		fmt.Println("end---------------------")
	}()
	// 订阅channel1这个channel
	sub := client.Subscribe(channel)
	for {
		// 读取channel消息
		face, err := sub.Receive()
		if err != nil {
			fmt.Println(err)
			// handle error
		}

		// 检测收到的消息类型
		switch v := face.(type) {
		case *redis.Subscription:
			fmt.Println("订阅成功")
			// 订阅成功
		case *redis.Message:
			fmt.Println("subscribe.Message1---------------------")
			buf := bytes.NewBufferString(v.Payload)
			s, _ := buf.ReadByte()
			messageModel_, _ := demo.MessageModel().OnMessageModel(ProtoModel.DataTypeProto(s), buf.Bytes())
			msg := &messageModel_.Message
			if msg != nil {

				if err != nil {
					// 发送失败
					log.Println(err)
					// break
				}
				return
			}
			fmt.Print(messageModel_.Sendbody)
			//fmt.Println(string(buf.Bytes()))
			fmt.Println("v.Channel:", v.Channel)
			fmt.Println("v.Payload:", v.Payload)
			fmt.Println("v.Pattern:", v.Pattern)
			fmt.Println("subscribe.Message2---------------------")
		case *redis.Pong:
			// 收到Pong消息
		default:
			// handle error
		}
	}
	//fmt.Println("订阅————————————————————————————————end")
}

/*
* channelName 通道名称
max 最大并发
num 单次推送数量
*/
func push1(channelName string, max uint, num int) {
	now := time.Now()
	// fmt.Println(now.Unix()) // 1565084298 秒fmt.Println(now.UnixNano()) // 1565084298178502600 纳秒fmt.Println(now.UnixNano() / 1e6) // 1565084298178 毫秒
	fmt.Println("end【0 】——————————开始发布订阅消息—————————!")
	fmt.Println(now.UnixNano() / 1e6)
	fmt.Println(now.Unix())
	var b = 0
	g := utils.NewGoLimit(max) //max_num(最大允许并发数)设置为2
	for i := 0; i < num; i++ {
		var s = `{ "act": "toUid","type": "chat","msg": {"id":"` + strconv.Itoa(i) + `","time":"` + time.Now().String() + `","uid": "2","msg": "我很好","touid": "1"}}`
		if b%10000 == 0 {
			//fmt.Println("end【", b, "】——————————发布订阅消息中—————————!")
		}
		b++
		//尝试增加一个协程, 若已达到最大并发数,将阻塞
		g.Add()
		go func() {
			defer g.Done() //一个并发协程已经完成
			client.Publish(channelName, s)
		}()
		time.Sleep(1 * time.Second)
		//go client.Publish("channel1", s)
	}
	fmt.Println("耗时秒", (time.Now()).Unix()-now.Unix())
	fmt.Println("耗时毫秒", ((time.Now()).UnixNano()/1e6)-(now.UnixNano()/1e6))
	fmt.Println("end【", b, "】——————————发布订阅完毕—————————!")
}

/*
*channelName 通道名称
sleep 每条推送间隔时间 秒
num 单次推送数量
*/
func push2(channelName string, sleep int, num int) {
	for i := 0; i < num; i++ {
		time.Sleep(time.Duration(sleep) * time.Second)

		msg := demo.MessageModel().PushMessageModel(ProtoModel.DataTypeProto_MESSAGE, nil)
		_, err := client.Publish(channelName, msg).Result()
		if err != nil {
			fmt.Println("推送失败", err)
			//panic(err)
		}

	}
}
func main() {
	channelName := "chat"
	//go subs1(channelName, 1)
	go sub4(channelName)
	//go subs2()
	//push1(100, 10)
	push2(channelName, 5, 100)
	//push2()
	time.Sleep(3 * time.Second)
	fmt.Println("完毕")
	select {}
}
